import time
import re

from selenium.webdriver.common.keys import Keys

from hslib.desk_input import key_press, key_up
from hslib.webdriver.data_change import deal_inputdata
from qturboframe.lib.report.log import logger
from qturboframe.lib.webdriver.exceptions import SeleniumError

from qturboframe.public_ui.jresui2.textarea import TextArea
from qturboframe.public_ui.jresui2.calendar import Calendar
from qturboframe.public_ui.jresui2.radio import Radio
from qturboframe.public_ui.jresui2.checkbox import CheckBox
from qturboframe.public_ui.jresui2.timer import Timer
from qturboframe.public_ui.jresui2.select import Select
from qturboframe.public_ui.jresui2.tree import Tree
from qturboframe.public_ui.jresui2.calendarm97 import CalendarM97
from qturboframe.public_ui.jresui2.input_type import InputType

from .base_element import BaseElement


class Form(BaseElement):
    """
    jres2.0的表单操作

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _element: 控件元素webelement对象
     - timeout: 步骤操作的超时时间

    :Example:
     - 例1: Form(webelement)
     - 例2: Form({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: Form({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: Form({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    """
    def __init__(self, element_para, father=None, timeout=5):
        super().__init__(element_para, father, timeout)
        self.form = self._element
        
    def get_form_label_to_excel(self, filename, idname:list=list(), father=None):
        '''
        获取jres2.0的表单中所有标签并填入Excel

        :Args:
         - filename: Excel文件名，包含文件路径
         - idname: 表单的定位条件
         - idname[0]: 元素查找方式
         - idname[1]: 元素查找语句
         - idname[2]: 查找的辅助属性
         - father: table的祖先级元素，可以给表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            返回表单控件名称列表，list类型

        :Raises:
            SeleniumError: 表单格式不正确或者获取控件名称出错

        :Example:
         - 例1: form.get_form_label_to_excel("c:\test.xlsx")
         - 例2: form.get_form_label_to_excel("c:\test.xlsx",["xpath",",//*[@class='test']"])
         - 例3: form.get_form_label_to_excel("c:\test.xlsx",["xpath",",//*[@class='test']","text:客户信息"])
        '''
        try:
            form = self.form
            if idname and (len(idname) > 1 and len(idname) < 4):
                if len(idname) is 2:
                    form = father.find_element_by_attribute(idname[0], idname[1], timeout=self.timeout)
                else:
                    form = father.find_element_by_attribute(idname[0], idname[1], idname[2],
                                                            timeout=self.timeout)
            else:
                form = father.find_element_by_attribute('tag name', 'form', timeout=self.timeout)
            label_div = form.find_element_by_attribute('css selector', 'div.m-panel-body',
                                                       timeout=self.timeout)
            label_text = label_div.text
            textlist = re.findall(r'[^\n]+', label_text)
            temp_list = list()
            for text in textlist:
                if re.search('^\*', text):
                    text = text.replace(r'*', r'\*')
                temp_list.append(text)
            temp_list.insert(0, '序号')
            from hslib.excel import ExcelWrite
            xls = ExcelWrite()
            xls.write_data_by_row([temp_list])
            xls.save(filename)
            return temp_list
        except Exception as msg:
            logger.getlogger().error(str(msg))
            print(traceback.format_exc())
            raise SeleniumError(str(msg))

    def auto_fill(self, inputdata):
        '''
        jres2.0的表单一键抓取功能

        :Args:
         - inputdata: 输入数据，需要定位的表单抬头和待输入文本

        :Returns:
            操作失败返回false，成功返回true

        :Raises:
            SeleniumError: 表单填充出错

        :Example:
         - 例: Form.auto_fill({"客户信息":"1234","客户名称":"bob"})
        '''
        try:
            for input_key, input_value in inputdata.items():
                if input_value == '':
                    continue

                key, value, flag, label_seq = deal_inputdata(input_key, input_value)

                #form中tag标识在label中
                label = self.form.find_elements_by_attribute('css selector', 'label', 'text:' + key,timeout=1)
                div_xpath = './following-sibling::div[1]'
                if label:
                    label = label[0]
                elif not label:
                    raise SeleniumError("没有找到label为'{}'的元素".format(key))

                div = label.find_element_by_attribute('xpath', div_xpath, timeout=self.timeout)

                temp_pass = self.confirm_type(div, key, value, flag)
                if temp_pass is False:
                    return False
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))
        else:
            return True

    def confirm_type(self, div, key, value, flag):
        '''
        判断jres2.0的控件类型

        :Args:
         - div: label后的div
         - key: label文本
         - value: 控件赋值
         - flag: 控件操作标记

        :Returns:
            填充失败返回False

        :Example:
         - 例: Form.confirm_type(div, "客户信息","1234")
        '''
        re_textarea = r'u-textarea'
        re_textfield = r'u-textfield'
        re_typefield = r'u-typefield'
        re_password = r'u-password'
        re_passwordgroup = r'u-password-group'
        re_select = r'u-select'
        re_select_tree = r'hc_select-tree'
        re_time = r'hc_timepicker'
        re_cadenlar = r'u-calendar'
        re_cadenlarrange = r'u-calendar-range'
        re_cadenlargroup = r'u-calendar-group'
        re_cadenlarm97 = r'u-calendar-timePicker'
        inputs = self.get_all_form_control(div)
        logger.debug(key + '有' + str(len(inputs)) + '个input')
        for inputele in inputs:
            input_type = inputele.get_attribute('type')
            input_class = inputele.get_attribute('class')
            if re.search(re_textarea, input_class):
                logger.debug(key + '：多行文本')
                if self.deal_textarea(inputs[0], key, value, flag) is False:
                    return False
                return
            elif input_type == 'radio':
                logger.debug(key + '：普通单选按钮')
                if self.deal_radio(inputs, key, value, flag) is False:
                    return False
                return
            elif input_type == 'checkbox':
                logger.debug(key + '：普通复选框')
                if self.deal_checkbox(inputs, key, value, flag) is False:
                    return False
                return True
            elif input_type == 'text' or input_type == 'password':
                logger.debug(key + '：文本框/密码框格式')
                if re.search(re_passwordgroup, input_class):
                    logger.debug(key + '：密码组')
                    if self.deal_password_group(inputs, key, value, flag) is False:
                        return False
                    return
                elif (re.search(re_textfield, input_class) or re.search(re_typefield, input_class) or
                      re.search(re_password, input_class)):
                    logger.debug(key + '：文本/金额/密码')
                    if self.deal_text(inputele, key, value, flag) is False:
                        return False
                    return
                elif re.search(re_time, input_class):
                    logger.debug(key + '：时间选择框')
                    if self.deal_timer(inputele, key, value, flag) is False:
                        return False
                    return
                elif re.search(re_select_tree, input_class):
                    logger.debug(key + '：下拉选择树，包括树形单选、树形复选')
                    # 增加TAB键动作切换文本框聚焦，保证有关联关系的下拉框默认值显示正确
                    if inputele.is_enabled():
                        inputele.send_keys(Keys.TAB)
                    if self.deal_select_tree(inputele, key, value, flag) is False:
                        return False
                    else:
                        # 增加TAB键动作切换文本框聚焦，保证下拉框选项div消失
                        if inputele.is_enabled():
                            inputele.send_keys(Keys.TAB)
                    return
                elif re.search(re_select, input_class):
                    logger.debug(key + '：下拉选择，包括单选、复选')
                    # 增加TAB键动作切换文本框聚焦，保证有关联关系的下拉框默认值显示正确
                    if inputele.is_enabled():
                        inputele.send_keys(Keys.TAB)
                    if self.deal_select(inputele, key, value, flag) is False:
                        return False
                    else:
                        # 增加TAB键动作切换文本框聚焦，保证下拉框选项div消失
                        if inputele.is_enabled() and inputele.is_displayed():
                            inputele.send_keys(Keys.TAB)
                    return
                elif re.search(re_cadenlar, input_class):
                    if (re.search(re_cadenlarm97, input_class) and
                            re.search(re_cadenlargroup, input_class)):
                        logger.debug(key + '：m97日历组')
                        if self.deal_calendar_m97_group(inputs, key, value, flag) is False:
                            return False
                        return
                    elif re.search(re_cadenlarm97, input_class):
                        logger.debug(key + '：m97日历')
                        if self.deal_calendar_m97(inputele, key, value, flag) is False:
                            return False
                        return
                    elif re.search(re_cadenlarrange, input_class):
                        logger.debug(key + '：双屏日历组')
                        if self.deal_calendar_range(inputele, key, value, flag) is False:
                            return False
                        return
                    elif re.search(re_cadenlargroup, input_class):
                        logger.debug(key + '：单屏日历组')
                        if self.deal_calendar_group(inputs, key, value, flag) is False:
                            return False
                        return
                    else:
                        logger.debug(key + '：日历')
                        if self.deal_calendar(inputele, key, value, flag) is False:
                            return False
                        return
                else:
                    logger.warn(key + '：不是日历控件！')
                    return False
            else:
                logger.warn(key + '：不是文本框/密码框格式控件！')
                return False
        else:
            logger.warn(key + '：不是表单控件！')
            return False

    def get_all_form_control(self, div):
        '''
        获取jres2.0的所有Form控件

        :Args:
         - updiv: 控件所在祖先节点，label的父节点

        :Returns:
            返回控件列表

        :Example:
         - 例: form.get_all_form_control(div)
        '''
        re_none = r'display:\s*none;'
        inputs = div.find_elements_by_attribute('tag name', 'input', timeout=1)
        typelist = ['text', 'password', 'radio', 'checkbox']
        i = 0
        if inputs:
            while i < len(inputs):
                input_type = inputs[i].get_attribute('type')
                input_style = inputs[i].get_attribute('style')
                if input_type not in typelist or re.search(re_none, input_style):
                    inputs.remove(inputs[i])
                else:
                    i += 1
            return inputs
        else:
            inputs = div.find_elements_by_attribute('tag name', 'textarea', timeout=1)
            return inputs

    def deal_textarea(self, element, key, value, flag='assign'):
        '''
        处理jres2.0的多行文本框

        :Args:
         - element: 多行文本框控件
         - key: 控件名称
         - value: 填充值
         - flag: 操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 填充或判断值是出错

        :Example:
         - 例1: form.deal_textarea(text_area_element, "客户信息", "123456")
         - 例2: form.deal_textarea(text_area_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_textarea(text_area_element, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_textarea(text_area_element, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_textarea(text_area_element, "客户信息", "", flag = 'clear')
        '''
        try:
            textarea = TextArea(element)
            text = value[0]
            if flag == 'assign' or flag=='':
                logger.info(key + '进行多行文本框填充。')
                textarea.set_value(text)
                return
            elif flag == 'readonly':
                logger.info(key + '进行多行文本框只读检查。')
                return textarea.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行多行文本框默认值检查。')
                return textarea.is_default(text)
            elif flag == 'readonlydefault':
                logger.info(key + '进行多行文本框默认值和只读检查。')
                check1 = textarea.is_readonly()
                check2 = textarea.is_default(text)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行多行文本框清除。')
                inputele.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_radio(self, elements, key, value, flag='assign'):
        '''
        处理jres2.0的单选按钮

        :Args:
         - elements: 单选按钮
         - key: 控件名称
         - value: 选择项
         - flag: 操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_radio(radio_elements, "客户信息", "123456")
         - 例2: form.deal_radio(radio_elements, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_radio(radio_elements, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_radio(radio_elements, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_radio(radio_elements, "客户信息", "", flag = 'clear')
        '''
        try:
            radio = Radio(elements)
            text = value[0]
            if flag == 'assign' or flag=='':
                logger.info(key + '进行单选按钮选择。')
                radio.set_value(text)
                return
            elif flag == 'readonly':
                logger.info(key + '进行单选按钮只读检查。')
                return radio.is_readonly_for_radio()
            elif flag == 'default':
                logger.info(key + '进行单选按钮默认值检查。')
                return radio.is_default(text)
            elif flag == 'readonlydefault':
                logger.info(key + '进行单选按钮默认值和只读检查。')
                check1 = radio.is_readonly_for_radio()
                check2 = radio.is_default(text)
                if check1 and check2:
                    return True
                else:
                    return False
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_checkbox(self, elements, key, value, flag='assign'):
        '''
        处理jres2.0的普通复选框

        :Args:
         - inputs: 复选框控件组
         - key: 控件名称
         - value: 选择项，list类型
         - flag: 操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_checkbox(radio_elements, "客户信息", "123456")
         - 例2: form.deal_checkbox(radio_elements, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_checkbox(radio_elements, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_checkbox(radio_elements, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_checkbox(radio_elements, "客户信息", "", flag = 'clear')
        '''
        try:
            checkbox = CheckBox(elements)
            if flag == 'all':
                logger.info(key + '进行复选框全选。')
                return checkbox.set_value()
            elif flag == 'assign' or flag=='':
                logger.info(key + '进行复选框选择。')
                return checkbox.set_value(value)
            elif flag == 'readonly':
                logger.info(key + '进行复选框只读检查。')
                return checkbox.is_readonly_for_checkbox()
            elif flag == 'default':
                logger.info(key + '进行复选框默认值检查。')
                return checkbox.is_default(value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行复选框默认值和只读检查。')
                check1 = checkbox.is_readonly_for_checkbox()
                check2 = checkbox.is_default(value)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行复选框清除。')
                for inputele in inputs:
                    if inputele.get_attribute('checked') == 'checked':
                        inputele.secure_click()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_text(self, element, key, value, flag='assign'):
        '''
        处理jres2.0的文本框

        :Args:
         - inputele: 文本框控件
         - key: 控件名称
         - value: 填充值
         - flag: 操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 填充或判断值是出错

        :Example:
         - 例1: form.deal_text(input_element, "客户信息", "123456")
         - 例2: form.deal_text(input_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_text(input_element, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_text(input_element, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_text(input_element, "客户信息", "", flag = 'clear')
        '''
        try:
            input_type = InputType(element)
            text = value[0]
            if flag == 'assign' or flag=='':
                logger.info(key + '进行文本框填充。')
                # 输入前先清空，再双击全选内容，保证输入值显示正确
                input_type.clear()
                #self._driver.doubleclick(inputele)
                self._driver.execute_script('arguments[0].click();', element)
                key_press(['ctrl', 'a'])
                key_up(['ctrl', 'a'])
                input_type.set_value(text)
                return
            elif flag == 'readonly':
                logger.info(key + '进行文本框只读检查。')
                return input_type.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行文本框默认值检查。')
                return input_type.is_default(text)
            elif flag == 'readonlydefault':
                logger.info(key + '进行文本框默认值和只读检查。')
                check1 = input_type.is_readonly()
                check2 = input_type.is_default(text)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行文本框清除。')
                input_type.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_password_group(self, inputs, key, value, flag='assign'):
        '''
        处理jres2.0的密码框组

        :Args:
         - inputs: 密码组控件
         - key: 控件名称
         - value: 一组填充值，list类型
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 填充或判断值是出错

        :Example:
         - 例1: form.deal_password_group(input_element, "客户信息", "123456")
         - 例2: form.deal_password_group(input_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_password_group(input_element, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_password_group(input_element, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_password_group(input_element, "客户信息", "", flag = 'clear')
        '''
        try:
            text1 = value[0]
            if len(value) < 2:
                text2 = value[0]
            else:
                text2 = value[1]
            # pswgroup = InputType(self._driver)
            if flag == 'assign':
                logger.info(key + '进行密码框组填充。')
                inputs[0].send_keys(text1)
                inputs[1].send_keys(text2)
                return
            elif flag == 'readonly':
                logger.info(key + '进行密码框组只读检查。')
                return InputType.is_readonly_for_group(inputs)
            elif flag == 'default':
                logger.info(key + '进行密码框组默认值检查。')
                return InputType.is_default_for_group(inputs, value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行密码框组默认值和只读检查。')
                check1 = InputType.is_readonly_for_group(inputs)
                check2 = InputType.is_default_for_group(inputs, value)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行密码框组清除。')
                inputs[0].clear()
                inputs[1].clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_select(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的下拉框

        :Args:
         - inputele: 下拉框控件
         - key: 控件名称
         - value: 下拉选项，list类型
         - flag: 操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_select(input_element, "客户信息", "123456")
         - 例2: form.deal_select(input_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_select(input_element, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_select(input_element, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_select(input_element, "客户信息", "", flag = 'clear')
        '''
        try:
            # select = Select(self._driver)
            if flag == 'assign' or flag == 'all' or flag=='':
                #inputele.Click()
                # 元素被遮挡，采用JS注入元素点击
                self._driver.execute_script('arguments[0].click();', inputele)
                displayeddiv = self._driver.find_element_by_attribute(
                    'xpath', '//div[@class="hc_checkboxdiv" and contains(@style, "display: block")]',
                    timeout=self.timeout)
                if 'true' == displayeddiv.get_attribute('multiple_line'):
                    logger.debug('多选下拉框')
                    ul = displayeddiv.find_element_by_attribute('tag name', 'ul', timeout=self.timeout)
                    if flag == 'all':
                        logger.info(key + '进行复选下拉框全选。')
                        return Select(ul).set_value_for_multiple()
                    elif flag == 'assign':
                        logger.info(key + '进行复选下拉框选择。')
                        return Select(ul).set_value_for_multiple(value)
                else:
                    ul = displayeddiv.find_element_by_attribute('tag name', 'ul', timeout=self.timeout)
                    logger.info(key + '进行单选下拉框选择。')
                    Select(ul).set_value_for_single(value)
                    return
            elif flag == 'readonly':
                logger.info(key + '进行下拉框只读检查。')
                return inputele.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行下拉框默认值检查。')
                return BaseElement(inputele).is_default(value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行下拉框默认值和只读检查。')
                check1 = inputele.is_readonly()
                check2 = BaseElement(inputele).is_default(value[0])
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行下拉框清除。')
                inputele.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_select_tree(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的树形结构的下拉框

        :Args:
         - inputele: 下拉框控件
         - key: 控件名称
         - value: 选择项
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_select_tree(input_element, "客户信息", "123456")
         - 例2: form.deal_select_tree(input_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_select_tree(input_element, "客户信息", "123456", flag = 'default')
         - 例4: form.deal_select_tree(input_element, "客户信息", "123456", flag = 'readonlydefault')
         - 例5: form.deal_select_tree(input_element, "客户信息", "", flag = 'clear')
        '''
        try:
            # select_tree = Tree(self._driver)
            if flag == 'assign' or flag == 'all':
                inputele.secure_click()
                #self._driver.executeScript(js='arguments[0].click();', ElementObject=inputele)
                displayeddiv = self._driver.find_element_by_attribute(
                    'xpath', '//div[@class="hc_selectbox-tree-div"]', 'style:display:\s*block;',
                    timeout=self.timeout)
                spans = displayeddiv.find_element_by_attribute(
                    'xpath', './div/ul[@class=\'ztree\']/li[1]/span', timeout=self.timeout)
                selecttree_flag = 0
                for span in spans:
                    if 'chk' in span.get_attribute('class'):
                        selecttree_flag += 1
                if selecttree_flag > 0:
                    logger.debug('多选下拉选择树')
                    if flag == 'all':
                        logger.info(key + '进行复选下拉树全选。')
                        Tree(displayeddiv).get_node_by_value('all', flag=1)
                    elif flag == 'assign':
                        logger.info(key + '进行复选下拉树选择。')
                        Tree(displayeddiv).get_node_by_value(value, flag=1)
                    return
                else:
                    logger.info(key + '进行单选下拉树选择。')
                    Tree(displayeddiv).get_node_by_value(value, flag=0)
                    return
            elif flag == 'readonly':
                logger.info(key + '进行下拉树框只读检查。')
                return inputele.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行下拉树框默认值检查。')
                return BaseElement(inputele).is_default(value[0])
            elif flag == 'readonlydefault':
                logger.info(key + '进行下拉树框默认值和只读检查。')
                check1 = inputele.is_readonly()
                check2 = BaseElement(inputele).is_default(value[0])
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行下拉树框清除。')
                inputele.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_calendar(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的日历控件

        :Args:
         - inputele: 日历框控件
         - key: 控件名称
         - value: 日期格式的日期，yy-mm-dd\yy-mm-dd hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_calendar(input_element, "客户信息", "20200120")
         - 例2: form.deal_calendar(input_element, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_calendar(input_element, "客户信息", "20200120", flag = 'default')
         - 例4: form.deal_calendar(input_element, "客户信息", "20200120", flag = 'readonlydefault')
         - 例5: form.deal_calendar(input_element, "客户信息", "", flag = 'clear')
        '''
        re_displayblock = r'display:\s*block;*'
        try:
            # calendar = Calendar(self._driver)
            calendar = Calendar(inputele)
            text = value[0]
            if flag == 'assign' or flag=='':
                xpath_1 = "./following-sibling::i[contains(@class,'u-calendar-down')]"
                xpath_2 = "./following-sibling::i[contains(@class,'u-calendar-group-down')]"
                xpath = xpath_1 + " | " + xpath_2
                click_i = inputele.find_element_by_attribute('xpath', xpath, timeout=self.timeout)
                #click_i.Click()
                self._driver.execute_script('arguments[0].click();', click_i)
                
                xpath = ".//div[contains(@class, 'dropdown-menu') and not(contains(@style,'display: none')) and not(contains(@class,'datetimepicker-dropdown-bottom'))]"
                temps = self._driver.find_elements_by_attribute('xpath', xpath, timeout=self.timeout)
                updiv = None
                for temp in temps:
                    if temp.is_displayed():
                        updiv = temp
                        break
                logger.info(key + '进行日历选择。')
                Calendar(updiv).set_value(text)
                # calendar.set_value(updiv, text)
                return
            elif flag == 'readonly':
                logger.info(key + '进行日历只读检查。')
                return Calendar(inputele).is_readonly()
            elif flag == 'default':
                logger.info(key + '进行日历默认值检查。')
                return Calendar(inputele).is_default(text)
            elif flag == 'readonlydefault':
                logger.info(key + '进行日历默认值和只读检查。')
                check1 = inputele.is_readonly()
                check2 = Calendar(inputele).is_default(text)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行日历清除。')
                inputele.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_calendar_group(self, inputs, key, value, flag='assign'):
        '''
        处理jres2.0的日历控件组

        :Args:
         - inputs: 日历控件组
         - key: 控件名称
         - value: 一组日期值，yy-mm-dd\yy-mm-dd hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_calendar_group(input_elements, "客户信息", "20200120")
         - 例2: form.deal_calendar_group(input_elements, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_calendar_group(input_elements, "客户信息", "20200120", flag = 'default')
         - 例4: form.deal_calendar_group(input_elements, "客户信息", "20200120", flag = 'readonlydefault')
         - 例5: form.deal_calendar_group(input_elements, "客户信息", "", flag = 'clear')
        '''
        re_displayblock = r'display:\s*block;*'
        re_displaynone = r'display:\s*none;*'
        try:
            # calendar = Calendar(self._driver)
            inputeles = list()
            for inputele in inputs:
                if re.search(re_displaynone, inputele.get_attribute('style')) or not('text' in inputele.get_attribute("type")):
                    logger.debug('元素不可见。')
                    continue
                inputeles.append(inputele)
            if flag == 'assign' or flag=='':
                # logger.info(key + '进行日历组填充。')
                i = 0
                for inputele in inputeles:
                    if len(value) < 2:
                        text = value[0]
                    else:
                        text = value[i]
                        i += 1
                    xpath = "./following-sibling::i[contains(@class,'u-calendar-group-down')]"
                    click_i = inputele.find_element_by_attribute('xpath', xpath, timeout=self.timeout)
                    self._driver.execute_script('arguments[0].click();', click_i)

                    xpath = ".//div[contains(@class, 'dropdown-menu') and not(contains(@style,'display: none')) and not(contains(@class,'datetimepicker-dropdown-bottom'))]"
                    updiv = self._driver.find_element_by_attribute('xpath', xpath, timeout=self.timeout)
                    # logger.info(key + '进行日历选择。')
                    Calendar(updiv).set_value(text)
                return
            elif flag == 'readonly':
                logger.info(key + '进行日历组只读检查。')
                return Calendar.is_readonly_for_group(inputeles)
            elif flag == 'default':
                logger.info(key + '进行日历组默认值检查。')
                return Calendar.is_default_for_group(inputeles, value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行日历组默认值和只读检查。')
                check1 = Calendar.is_readonly_for_group(inputeles)
                check2 = Calendar.is_default_for_group(inputeles, value)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行日历组清除。')
                inputeles[0].clear()
                inputeles[1].clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_calendar_range(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的日历范围控件

        :Args:
         - inputele: 日历范围控件
         - key: 控件名称
         - value: 一组日期值，yy-mm-dd\yy-mm-dd hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错

        :Example:
         - 例1: form.deal_calendar_range(input_elements, "客户信息", "20200120")
         - 例2: form.deal_calendar_range(input_elements, "客户信息", "", flag = 'readonly')
         - 例3: form.deal_calendar_range(input_elements, "客户信息", "20200120", flag = 'default')
         - 例4: form.deal_calendar_range(input_elements, "客户信息", "20200120", flag = 'readonlydefault')
         - 例5: form.deal_calendar_range(input_elements, "客户信息", "", flag = 'clear')
        '''
        re_displayblock = r'display:\s*block;*'
        try:
            # calendar = Calendar(self._driver)
            if flag == 'assign' or flag=='':
                inputele.secure_click()
                updiv = inputele.find_element_by_attribute(
                    'xpath', '//div[@class=\"h_screen\"]/following-sibling::div',
                    'class:daterangepicker,style:' + re_displayblock, timeout=self.timeout)
                logger.info(key + '进行日历组填充。')
                Calendar(updiv).set_value_for_range(value)
                return
            elif flag == 'readonly':
                logger.info(key + '进行日历组只读检查。')
                return inputele.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行日历组默认值检查。')
                return Calendar.is_default_for_range(inputele, value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行日历组默认值和只读检查。')
                check1 = inputele.is_readonly()
                check2 = Calendar.is_default_for_range(inputele, value)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行日历组清除。')
                inputele.clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_calendar_m97(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的m97日历控件

        :Args:
         - inputele: m97日历控件
         - key: 控件名称
         - value: 日期格式的日期，yy-mm-dd\yy-mm-dd hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错
        '''
        try:
            text = value[0]
            calendar = CalendarM97(inputele)
            if flag == 'assign' or flag=='':
                logger.info(key + '进行97日历选择。')
                calendar.set_value(inputele, text)
                # 通过查找label返回到当前frame
                self._driver.find_elements_by_attribute(
                    'css selector', 'label.unit-label,text:.*' + key + '.*',
                    timeout=1, switchframe=True)
                return
            elif flag == 'readonly':
                logger.info(key + '进行97日历只读检查。')
                return inputele.is_readonly()
            elif flag == 'clear':
                logger.info(key + '进行97日历清除。')
                inputele.clear()
                return True
            else:
                logger.warn(key + '未进行任何操作。')
                return False
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_calendar_m97_group(self, inputs, key, value, flag='assign'):
        '''
        处理jres2.0的m97日历控件组

        :Args:
         - inputs: 一组m97日历控件
         - key: 控件名称
         - value: 一组日期格式的日期值，yy-mm-dd\yy-mm-dd hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错
        '''
        re_displaynone = r'display:\s*none;*'
        # calendar = CalendarM97(self._driver)
        try:
            inputeles = list()
            for inputele in inputs:
                if re.search(re_displaynone, inputele.get_attribute('style')):
                    logger.debug('元素不可见。')
                    continue
                inputeles.append(inputele)
            if flag == 'assign' or flag=='':
                logger.info(key + '进行97日历组选择。')
                for i in range(0, len(inputeles)):
                    calendar = CalendarM97(inputeles[i])
                    calendar.set_value(inputeles[i], value[i])
                    # 通过查找label返回到当前frame
                    self._driver.find_elements_by_attribute(
                        'css selector:label.unit-label,text:.*' + key + '.*',
                        timeout=1, switchFrame=True)
                return True
            elif flag == 'readonly':
                logger.info(key + '进行97日历组只读检查。')
                return CalendarM97.is_readonly_for_group(inputeles)
            elif flag == 'clear':
                logger.info(key + '进行97日历组清除。')
                inputeles[0].clear()
                inputeles[1].clear()
                return
            else:
                logger.warn(key + '未进行任何操作。')
                return False
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))

    def deal_timer(self, inputele, key, value, flag='assign'):
        '''
        处理jres2.0的时间控件

        :Args:
         - inputele: 时间控件
         - key: 控件名称
         - value: 时间格式的时间值，hh:mm:ss
         - flag:操作标记

        :Returns:
            判断失败返回False

        :Raises:
            SeleniumError: 选择或判断值是出错
        '''
        try:
            # timer = Timer(self._driver)
            re_displayblock = r'display:\s*block;*'
            if flag == 'assign':
                logger.info(key + '进行时间选择。')
                inputele.secure_click()
                displayeddiv = self._driver.find_element_by_attribute(
                    'xpath', '//div[@class="hc_hide_div-time"]/div[@class="time-select-dropdown"]',
                    'style:' + re_displayblock, timeout=self.timeout)
                updiv = displayeddiv.find_element_by_attribute(
                    'tag name', 'div,class:h-time-picker-cells', timeout=self.timeout)
                Timer(updiv).set_value(value)
                inputele.send_keys(Keys.TAB)
                return True
            elif flag == 'readonly':
                logger.info(key + '进行时间只读检查。')
                return inputele.is_readonly()
            elif flag == 'default':
                logger.info(key + '进行时间默认值检查。')
                return Timer(inputele).is_default(value)
            elif flag == 'readonlydefault':
                logger.info(key + '进行时间默认值和只读检查。')
                check1 = inputele.is_readonly()
                check2 = Timer(inputele).is_default(value)
                if check1 and check2:
                    return True
                else:
                    return False
            elif flag == 'clear':
                logger.info(key + '进行时间清除。')
                inputele.clear()
                return True
            else:
                logger.warn(key + '未进行任何操作。')
                return False
        except Exception as msg:
            logger.error(str(msg))
            raise SeleniumError(str(msg))
